package dev.ece.util.tools;

import dev.ece.util.GLUtils;
import dev.ece.util.lib.Matrix4f;
import dev.ece.util.lib.Vector3f;

/**
 * @author 潜行的青衣
 * @see
 */
public class Camera {

	public final Vector3f position = new Vector3f();	//观察位置
	
	public final Vector3f center = new Vector3f();	//观察中心
	
	public final Vector3f head = new Vector3f();		//头朝向
	
	public Camera() {
		this.head.set(0, 1f, 0);
	}
	
	public final void lookAt() {
		GLUtils.lookAt(position, center, head);
	}
	
	public final void lookAt(Matrix4f matrix) {
		matrix.lookAt(position, center, head);
	}
	
	public final void setPosition(Vector3f position) {
		this.setPosition(position.getX(), position.getY(), position.getZ());
	}

	public final void setPosition(float x, float y, float z) {
		this.position.set(x, y, z);
		this.center.set(x, y, z - 1);
		this.head.set(0, 1f, 0);
	}
	
	/**
	 * 前进
	 * @author 潜行的青衣
	 * @version
	 * @param distance
	 */
	public void forward(float distance) {
		//前进方向向量
		Vector3f vector = new Vector3f();
		vector.splus(this.position, this.center);
		vector.normalize();
		vector.setLength(distance);
		this.position.add(vector);
		this.center.add(vector);
	}
	
	/**
	 * 后退
	 * @author 潜行的青衣
	 * @version
	 */
	public void retreat(float distance) {
		//前进方向相反的向量
		Vector3f vector = new Vector3f();
		vector.splus(this.center, this.position);
		vector.normalize();
		vector.setLength(distance);
		this.position.add(vector);
		this.center.add(vector);
	}
	
	/**
	 * 上平移
	 * @param distance
	 */
	public void up(float distance) {
		//左侧方向向量
		Vector3f vector = new Vector3f();
		Vector3f forward = new Vector3f();
		forward.set(this.center);
		forward.setY(position.getY());
		vector.splus(this.position, forward);
		vector.normalize();
		vector.setLength(distance);
		this.position.add(vector);
		this.center.add(vector);
	}
	
	/**
	 * 下平移
	 * @param distance
	 */
	public void down(float distance) {
		//左侧方向向量
		Vector3f vector = new Vector3f();
		Vector3f forward = new Vector3f();
		forward.set(this.center);
		forward.setY(position.getY());
		vector.splus(forward, this.position);
		vector.normalize();
		vector.setLength(distance);
		this.position.add(vector);
		this.center.add(vector);
	}
	
	
	/**
	 * 左平移
	 * @author 潜行的青衣
	 * @version
	 * @param distance
	 */
	public void left(float distance) {
		Matrix4f matrix = new Matrix4f();
		matrix.identity();
		matrix.rotate(0, 1f, 0, 90);
		//左侧方向向量
		Vector3f vector = new Vector3f();
		Vector3f forward = new Vector3f();
		forward.set(this.center);
		forward.setY(position.getY());
		vector.splus(this.position, forward);
		vector.normalize();
		matrix.transform(vector);
		vector.setLength(distance);
		this.position.add(vector);
		this.center.add(vector);
	}
	
	/**
	 * 右平移
	 * @author 潜行的青衣
	 * @version
	 * @param distance
	 */
	public void right(float distance) {
		Matrix4f matrix = new Matrix4f();
		matrix.identity();
		matrix.rotate(0, 1f, 0, - 90);
		//前进方向向量
		Vector3f vector = new Vector3f();
		Vector3f forward = new Vector3f();
		forward.set(this.center);
		forward.setY(position.getY());
		vector.splus(this.position, forward);
		vector.normalize();
		matrix.transform(vector);
		vector.setLength(distance);
		this.position.add(vector);
		this.center.add(vector);
	}
	
	/**
	 * 向上旋转
	 * @author 潜行的青衣
	 * @version
	 * @param angle
	 */
	public void turnUp(float angle) {
		Matrix4f matrix = new Matrix4f();
		matrix.identity();
		
		//所看方向向量
		Vector3f vector = new Vector3f();
		vector.splus(this.position, this.center);
		//计算法线向量（旋转方向）
		NormalUtils.buildNormal(this.head, vector, vector);
		
		matrix.rotate(vector.getX(), vector.getY(), vector.getZ(), -angle);
		this.center.splus(this.position, this.center);
		matrix.transform(this.center);
		this.center.add(this.position);
		matrix.transform(this.head);
	}
	
	/**
	 * 向右旋转
	 * @author 潜行的青衣
	 * @version
	 * @param angle
	 */
	public void turnRight(float angle) {
		Matrix4f matrix = new Matrix4f();
		matrix.identity();
		matrix.rotate(0, 1, 0, - angle);
		this.center.splus(this.position, this.center);
		matrix.transform(this.center);
		this.center.add(this.position);
		matrix.transform(this.head);
	}
	
	/**
	 * 向下旋转
	 * @author 潜行的青衣
	 * @version
	 * @param angle 角度
	 */
	public void turnDown(float angle) {
		Matrix4f matrix = new Matrix4f();
		matrix.identity();
		
		//所看方向向量
		Vector3f vector = new Vector3f();
		vector.splus(this.position, this.center);
		NormalUtils.buildNormal(this.head, vector, vector);
		
		matrix.rotate(vector.getX(), vector.getY(), vector.getZ(), angle);
		this.center.splus(this.position, this.center);
		matrix.transform(this.center);
		this.center.add(this.position);
		matrix.transform(this.head);
	}
	
	/**
	 * 向左旋转
	 * @author 潜行的青衣
	 * @version
	 * @param angle
	 */
	public void turnLeft(float angle) {
		Matrix4f matrix = new Matrix4f();
		matrix.identity();
		matrix.rotate(0, 1, 0, angle);
		this.center.splus(this.position, this.center);
		matrix.transform(this.center);
		this.center.add(this.position);
		matrix.transform(this.head);
	}
}
